{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 动态系统建模\n",
    "Drake与Simulink的主要不同在于Drake更注重系统的内部信息。。。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1、写成自己的动力学方程\n",
    "每个用户系统都可以使用pydrake.systems.framework.LeafSystem类写出来。\n",
    "\n",
    "但是，我们感兴趣的很多动态系统是以状态空间形式表示的向量域，其中通常用$x$表示状态向量，用$u$表示输入向量，并用$y$表示输出向量。为了更容易的表示这种形式的系统，我们提供了另一个子类pydrake.systems.primitives.SymbolicVectorSystem，来表示这些简单系统\n",
    "\n",
    "![向量系统](./images/vector-system.png)\n",
    "\n",
    "### 1.1 使用SymbolicVectorSystem\n",
    "考虑一个基本的线性时间、非线性、输入-输出动态系统，由厦门的状态空间方程描述：\n",
    "$$\n",
    "\\dot{x} = f(t,x,u)  \\\\\n",
    "y = g(t,x,u)  \\\\\n",
    "$$\n",
    "在pydrake中，可以实现由Drake的符号引擎支撑的任何系统，比如\n",
    "$$\n",
    "\\dot{x} = -x+x^3  \\\\\n",
    "y = x  \\\\\n",
    "$$\n",
    "该系统的输入为0，只有一个状态变量，和一个输出。在Drake中，使用下面的代码实现该系统："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pydrake.symbolic import Variable\n",
    "from pydrake.systems.primitives import SymbolicVectorSystem\n",
    "\n",
    "# Define a new symbolic Variable\n",
    "x = Variable(\"x\")\n",
    "\n",
    "# Define the System.  \n",
    "continuous_vector_system = SymbolicVectorSystem(state=[x], dynamics=[-x + x**3], output=[x])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这就行了。continuous_vector_system现在是Drake系统类的一个实例，可以使用了。\n",
    "\n",
    "同样也可以实例化一个离散时间系统，这里先略。。。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.2 使用LeafSystem生成系统\n",
    "通过LeafSystem，Drake可支持生成各种输入输出、混合离散时间和连续时间动力学、混合动态以及约束、甚至随机特性的系统。\n",
    "下面是一个例子："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pydrake.systems.framework import BasicVector, LeafSystem\n",
    "\n",
    "# Define the system.\n",
    "class SimpleContinuousTimeSystem(LeafSystem):\n",
    "    def __init__(self):\n",
    "        LeafSystem.__init__(self)\n",
    "        \n",
    "        self.DeclareContinuousState(1)             # One state variable.\n",
    "        self.DeclareVectorOutputPort(\"y\", BasicVector(1), self.CopyStateOut)           # One output.\n",
    "\n",
    "    # xdot(t) = -x(t) + x^3(t)\n",
    "    def DoCalcTimeDerivatives(self, context, derivatives):\n",
    "        x = context.get_continuous_state_vector().GetAtIndex(0)\n",
    "        xdot = -x + x**3\n",
    "        derivatives.get_mutable_vector().SetAtIndex(0, xdot)\n",
    "\n",
    "    # y = x\n",
    "    def CopyStateOut(self, context, output):\n",
    "        x = context.get_continuous_state_vector().CopyToVector()\n",
    "        output.SetFromVector(x)\n",
    "\n",
    "# Instantiate the System        \n",
    "continuous_system = SimpleContinuousTimeSystem()\n",
    "\n",
    "\n",
    "# Define the system.\n",
    "class SimpleDiscreteTimeSystem(LeafSystem):\n",
    "    def __init__(self):\n",
    "        LeafSystem.__init__(self)\n",
    "        \n",
    "        self.DeclareDiscreteState(1)             # One state variable.\n",
    "        self.DeclareVectorOutputPort(\"y\", BasicVector(1), self.CopyStateOut)           # One output.\n",
    "        self.DeclarePeriodicDiscreteUpdate(1.0)  # One second timestep.\n",
    "\n",
    "    # x[n+1] = x^3[n]\n",
    "    def DoCalcDiscreteVariableUpdates(self, context, events, discrete_state):\n",
    "        x = context.get_discrete_state_vector().GetAtIndex(0)\n",
    "        xnext = x**3\n",
    "        discrete_state.get_mutable_vector().SetAtIndex(0, xnext)\n",
    "\n",
    "    # y = x\n",
    "    def CopyStateOut(self, context, output):\n",
    "        x = context.get_discrete_state_vector().CopyToVector()\n",
    "        output.SetFromVector(x)\n",
    "\n",
    "# Instantiate the System        \n",
    "discrete_system = SimpleDiscreteTimeSystem()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "上面的代码实现了同1.1节一样的系统，但是这里不同的是，我们可以输入任意的方程，不需要pydrake.symbolic的支持。\n",
    "\n",
    "但是，使用这种方式生成的系统不支持Drake的autodiff和symbolic工具。要使用的话需要增加一些代码。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2、仿真\n",
    "一旦我们有了系统的对象，最简单的事就是进行仿真。这可以通过pydrake.framework.analysis.Simulator实现。\n",
    "\n",
    "为了显示仿真中的数据，我们可以在系统框图（diagram）中增加一个信号记录器（pydrake.framework.primitives.SignalLogger）。\n",
    "\n",
    "下面是一个例子："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "from pydrake.systems.analysis import Simulator\n",
    "from pydrake.systems.framework import DiagramBuilder\n",
    "from pydrake.systems.primitives import LogOutput\n",
    "\n",
    "# Create a simple block diagram containing our system.\n",
    "builder = DiagramBuilder()\n",
    "system = builder.AddSystem(SimpleContinuousTimeSystem())\n",
    "logger = LogOutput(system.get_output_port(0), builder)\n",
    "diagram = builder.Build()\n",
    "\n",
    "# Set the initial conditions, x(0).\n",
    "context = diagram.CreateDefaultContext()\n",
    "context.SetContinuousState([0.9])\n",
    "\n",
    "# Create the simulator, and simulate for 10 seconds.\n",
    "simulator = Simulator(diagram, context)\n",
    "simulator.AdvanceTo(10)\n",
    "\n",
    "# Plot the results.\n",
    "plt.figure()\n",
    "plt.plot(logger.sample_times(), logger.data().transpose())\n",
    "plt.xlabel('t')\n",
    "plt.ylabel('y(t)');\n",
    "# Create a simple block diagram containing our system.\n",
    "builder = DiagramBuilder()\n",
    "system = builder.AddSystem(SimpleDiscreteTimeSystem())\n",
    "logger = LogOutput(system.get_output_port(0), builder)\n",
    "diagram = builder.Build()\n",
    "\n",
    "# Create the simulator.\n",
    "simulator = Simulator(diagram)\n",
    "\n",
    "# Set the initial conditions, x(0).\n",
    "state = simulator.get_mutable_context().get_mutable_discrete_state_vector()\n",
    "state.SetFromVector([0.9])\n",
    "\n",
    "# Simulate for 10 seconds.\n",
    "simulator.AdvanceTo(10)\n",
    "\n",
    "# Plot the results.\n",
    "plt.figure()\n",
    "plt.stem(logger.sample_times(), logger.data().transpose(), use_line_collection=True)\n",
    "plt.xlabel('n')\n",
    "plt.ylabel('y[n]');"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对很多系统来说，仿真将比实际系统快很多。如果你想让仿真器慢下来，可以使用仿真器（Simulator）的set_target_realtime_rate()函数。\n",
    "\n",
    "## 系统“上下文”（Context）\n",
    "\n",
    "上下文（context）是Drake中的核心概念：它包含了所有动态信息，包括时间、状态、输入和系统参数。\n",
    "\n",
    "要注意的是，当输入端口没有全部连接时，上下文是不完整的。因此，对于一些系统，需要考虑使用端口的FixValue函数。\n",
    "\n",
    "## 系统的复合：Diagram和DiagramBuilde\n",
    "\n",
    "Drake的建模能力体现在可以将小的系统复合为更复杂的系统。其中的概念非常简单：我们使用DiagramBuilder类增加系统（AddSystem()）并连接（Connect()）框图的输入端口和输出端口。然后，调用Build()来生成新的框图实例。\n",
    "\n",
    "下面的例子中，我们连接三个子系统（一个平台、一个控制器和一个记录器），并把控制器的输入暴露给框图：\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "ename": "ModuleNotFoundError",
     "evalue": "No module named 'pydot'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mModuleNotFoundError\u001b[0m                       Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-5-b6c3d6593b9a>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      7\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mpydrake\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexamples\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpendulum\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mPendulumPlant\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      8\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mpydrake\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msystems\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcontrollers\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mPidController\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 9\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mpydrake\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msystems\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdrawing\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mplot_system_graphviz\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     10\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mpydrake\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msystems\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mprimitives\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mLogOutput\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/drake/lib/python3.6/site-packages/pydrake/systems/drawing.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      7\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mmatplotlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpyplot\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 8\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mpydot\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      9\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mpydrake\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcommon\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mtemp_directory\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'pydot'"
     ]
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "from pydrake.systems.framework import DiagramBuilder\n",
    "from pydrake.systems.analysis import Simulator\n",
    "from pydrake.examples.pendulum import PendulumPlant\n",
    "from pydrake.systems.controllers import PidController\n",
    "from pydrake.systems.drawing import plot_system_graphviz\n",
    "from pydrake.systems.primitives import LogOutput\n",
    "\n",
    "builder = DiagramBuilder()\n",
    "\n",
    "# First add the pendulum.\n",
    "pendulum = builder.AddSystem(PendulumPlant())\n",
    "pendulum.set_name(\"pendulum\")\n",
    "\n",
    "controller = builder.AddSystem(PidController(kp=[10.], ki=[1.], kd=[1.]))\n",
    "controller.set_name(\"controller\")\n",
    "\n",
    "# Now \"wire up\" the controller to the plant.\n",
    "builder.Connect(pendulum.get_state_output_port(), controller.get_input_port_estimated_state())\n",
    "builder.Connect(controller.get_output_port_control(), pendulum.get_input_port())\n",
    "\n",
    "# Make the desired_state input of the controller an input to the diagram.\n",
    "builder.ExportInput(controller.get_input_port_desired_state())\n",
    "\n",
    "# Log the state of the pendulum.\n",
    "logger = LogOutput(pendulum.get_state_output_port(), builder)\n",
    "logger.set_name(\"logger\")\n",
    "\n",
    "diagram = builder.Build()\n",
    "diagram.set_name(\"diagram\")\n",
    "\n",
    "plt.figure()\n",
    "plot_system_graphviz(diagram, max_depth=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
